Skip to content

feat(workflows): stop a manual v2 run after a block, and workflows run --stop-after - #8622

Merged
waleedlatif1 merged 4 commits into
stagingfrom
feat/workflow-run-stop-after
Oct 5, 2026
Merged

waleedlatif1 merged 4 commits into
stagingfrom
feat/workflow-run-stop-after

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Copilot subagents that debug a workflow can only test it by running the whole thing. In one slow production session, lanes re-ran a ~37 s workflow 124 times to check edits to individual blocks. A third of those runs repeated an input with no edit in between, lanes toggled blocks off and on 27 times to skip slow parts, and --from-block was never used. The main agent avoids this with run_block/run_from_block, but those run in the user's editor, so subagents cannot call them.

This PR lets a manual v2 run stop after a named block. Combined with the existing block entry, an agent (or anyone on the CLI) can re-run exactly one block server-side against a prior run's real upstream outputs:

sim workflows run <workflowId> --from-block <blockId> --source-run <runId> --stop-after <blockId> --select-output <Block>.result

The design estimate for sessions like the one above is about 27–32% less wall time and 17–22% lower cost. Most of that needs the worker change in simstudioai/mothership#596 to tell subagents to use the flag.

Design

  • Contract: apps/sim/lib/api/contracts/v2/workflows.ts adds an optional run.stopAfterBlockId to the manual run selection. It is valid with no entry, a trigger entry, or a block entry. Deployment runs cannot carry it (the field only exists on the manual variant), and async is already refused for manual runs.

  • Application operation: executeManualWorkflowOperation and executeManualWorkflowFromBlockOperation validate the stop block against the saved workflow before anything runs. Three cases are refused as 400:

    • a missing block (own-property lookup)
    • a disabled block
    • a block nested in a loop or parallel
    • a block the run cannot reach from its entry (the selected trigger or the run-from block, following saved edges and skipping disabled blocks)

    The engine stops only on an exact node id, so in each of these cases it would otherwise silently run everything after the entry, or stop after one loop iteration. This matches the editor, which offers "Run until block" only outside subflows. Loop and parallel containers themselves are allowed (the executor already resolves them to their end sentinel).

  • Executor: executeWorkflowCore now fails a run whose stop block is absent or disabled in the workflow it executes, instead of running everything. That closes the window between validation and the core's own draft load. It also covers the internal and Copilot run-until callers, which never validated the target.

  • Execute service: threads the trusted value to both the synchronous core and the streaming path, where the executor already supported stopAfterBlockId for the internal and Copilot routes. Like runFromBlock, it is rejected unless the run uses draft state.

  • Route: the v2 execute route maps the field into both manual operations; no new parsing.

  • CLI: --stop-after <blockId> on workflows run implies --manual, and fails locally with --async or an empty value. OpenAPI, the generated CLI API, and the CLI docs are regenerated.

Compatibility

  • Additive and optional, so existing callers are unchanged. An older server answers 400 to a body carrying stopAfterBlockId (strict body), and an older CLI rejects --stop-after as an unknown option.
  • Deploy order: this PR first, then simstudioai/mothership#596. The worker's prompt tells subagents to use --stop-after. If the worker shipped first, those calls would fail with "unknown option" until Sim deployed. The model would see the error and fall back to a full run, so nothing breaks, but the speedup would be lost. The worker's grammar is regenerated from this branch.
  • Rollback: reverting this PR is safe on its own. If the worker is already live, --stop-after calls return an error and lanes fall back to full runs. Roll the worker back too if that matters.
  • CI: the http-e2e job gains a step that boots a self-hosted app for the new E2E. Hosted billing admits a run only through a Redis usage reservation, and the SCIM suite asserts PostgreSQL rate-limit storage, so workflow execution gets its own app rather than adding Redis to the shared one. The job takes about 5 minutes against its 20-minute bound.

Test plan

  • E2E over real HTTP (apps/sim/scripts/test-workflow-stop-after-e2e.ts, in its own http-e2e step, JSON report at STOP_AFTER_E2E_REPORT_PATH). The fixture is Start → Slow (4 s wait) → Check → After. The checks:
    • A full manual run executes every block.
    • The CLI --from-block Check --source-run R --stop-after Check returns only Check.status. It finishes in under Slow's 4 s, which shows Slow was not re-run.
    • A trigger-entry run with stopAfterBlockId: Slow returns only Slow.
    • A block entry without the field still runs downstream.
    • These are refused with no run started (execution-log count unchanged): a stop block from another workflow, an empty one, a stop block upstream of the entry, and async (all 400), and a missing source run (404).
    • A source run from a different workflow is refused (404).
    • Passed locally against a self-hosted app on a disposable Postgres, with the same env as the CI step.
    • Red check: with the route's block-entry mapping removed, the single-block check fails (After.status present).
  • Unit tests for the operation boundary (execute-manual-workflow.test.ts). Each refusal asserts its own reason, before any execution or source-state read: a missing block, an inherited object key, a disabled block, a block reachable only through a disabled one, a loop-nested block, and an unreachable block (upstream of a block entry, or unconnected from the trigger). Removing any one guard turns its test red.
  • CLI tests (workflow-run-follow.test.ts): the wire body for --from-block … --stop-after, --stop-after alone or with --trigger implying manual, and the local refusals of --async and an empty value. Each fails without its code.
  • bun run type-check, bun run lint, bun run docs-manifest:check, and the block-registry check pass. check:audits passes after shrinking the unused-exports baseline: the E2E now imports two previously unused contract types.

…un --stop-after`

A manual v2 run can now name `run.stopAfterBlockId`; the run stops once that
block completes and downstream blocks do not execute. Combined with a block
entry on the same block, it re-runs exactly one block against a prior run's
persisted upstream outputs, server-side:

  sim workflows run W --from-block X --source-run R --stop-after X --select-output X.result

Agents verifying an edit no longer re-run every upstream block (often a slow
LLM or API call) or toggle blocks off to skip them.

- Contract: optional `stopAfterBlockId` on the manual run selection.
- Application: both manual operations refuse a block missing from the saved
  workflow or nested in a loop/parallel (the engine would otherwise run to the
  end or stop after one iteration), before anything runs.
- Execute service: threads the trusted value to the sync and stream paths.
- CLI: `--stop-after <blockId>` implies --manual and rejects --async.
- E2E: test-workflow-stop-after-e2e.ts against a running app; the http-e2e job
  gains a Redis service because hosted billing admits runs through a Redis
  usage reservation.
@waleedlatif1
waleedlatif1 requested a review from a team as a code owner October 5, 2026 11:21
@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 5, 2026 1:17pm UTC

Request Review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 15 files

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/lib/workflows/application/execute-manual-workflow.ts Outdated
Comment thread packages/sim-cli/src/commands/protocol/workflow-run-follow.ts Outdated
Comment thread apps/sim/lib/workflows/executor/execute-service.ts
@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Adds stop-after-block feature to manual workflow runs.

The PR appears safe to merge; no outstanding findings were identified.

Summary

This PR adds a stop-after target to manual v2 workflow runs, threads it through the executor, and exposes it as workflows run --stop-after in the CLI. It also adds validation, generated contract and documentation updates, and HTTP end-to-end coverage.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  CLI[CLI --stop-after] --> API[v2 execute route]
  API --> Validate[Validate saved target and entry reachability]
  Validate --> Service[Execute service]
  Service --> Core[Resolve stop target in executed workflow]
  Core --> Run[Execute through target block]
Loading

Reviews (3) · Last reviewed commit: "fix(workflows): the executor refuses a d..."

Comment thread apps/sim/lib/workflows/application/execute-manual-workflow.ts Outdated
Comment thread packages/sim-cli/src/commands/protocol/workflow-run-follow.ts Outdated
Comment thread apps/sim/lib/workflows/application/execute-manual-workflow.test.ts Outdated
…2E self-hosted

- The manual operations refuse a stop block the run cannot reach from its
  entry (an upstream block would let the run finish everything after the
  entry), and look blocks up as own properties.
- The executor fails a run whose stop block is absent from the workflow it
  executes, instead of running everything; this closes the window between
  validation and the executor's own draft load, for every caller.
- The CLI refuses an empty --stop-after rather than dropping it.
- CI: the stop-after E2E gets its own self-hosted app step; the SCIM suite
  asserts PostgreSQL rate-limit storage, so Redis is not added to that app.
  Fixture cleanup waits for run logs to finalize before deleting.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 16 files

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/lib/workflows/application/execute-manual-workflow.ts
…ough one

The executor omits disabled blocks from its graph, so a disabled stop target,
or one whose only path runs through a disabled block, is never reached and
the run would finish everything after the entry.
The serialized workflow keeps disabled blocks, but the DAG skips them, so a
disabled stop target would never be reached.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 16 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

This branch was previously deployed

1 inactive deployment
Preview — 92d726bd Deployed Oct 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant